/*!
 * vinculum
 * Copyright(c) 2017 azzly
 * MIT Licensed
 */
 
'use strict';

/**
 * Module dependencies.
 * @private
 */
const helper = require("../helper");
const CONST = require("../CONST");
const config = require("../config");
const debug = require("../debug")(__filename);
const datasource = require("../datasource");
const error = require("../HTTPErrors");
const cache = require('../cache');
const template = require('../template');
const utils = require('../utils');
const service = require('./service');
const action = require('./action');
 
/**
 * class.
 */
const appConst = {
	TABLE_PREFIX:CONST.TABLE_PREFIX
	,FILTER_TYPES:CONST.FILTER_TYPES
	,LOCK_TYPES:CONST.LOCK_TYPES
	,SERVICE_TYPES:CONST.SERVICE_TYPES
};

function dealCode(info,data,callback){
	let cssparams = _cssparams();
	template.renderStr(info.main_html,data).then(result=>{
		info.main_html = result;
		_minify();
	}).catch(err=>{
		console.error(err);
		_minify();
	});
	
	function _cssparams(){
		let ret = [];
		for(let key in data){
			ret.push('@' + key + ':"' + data[key] + '";');
		}
		return ret.join('\n');
	}

	
	function _minify(){
		utils.minifyHTML(info.main_html,(htmlerror,htmldata)=>{
			utils.babel_js(info.main_js,true,(jserror,jsdata)=>{
				utils.less_css(cssparams + info.main_css,true,(csserror,cssdata)=>{
					if(!htmlerror) info.main_html= htmldata;
					if(!jserror) info.main_js= jsdata;
					if(!csserror) info.main_css= cssdata;
					_dealResult();
				});
			});
		});
	}
	
	function _dealResult(){
		if(info.resources.length ===0 ) callback();
		let newresources = [];
		helper.async(info.resources,function(one,cb){
			let islocal = one.type === CONST.RESOURCE_TYPES.LOCAL;
			if(islocal && one.filetype === 'js'){
				utils.babel_js(one.main,true,(jserror,jsdata)=>{
						if(!jserror) one.main= jsdata;
						newresources.push(one);
						cb();
				});
			}else if(islocal && one.filetype === 'css'){
				utils.less_css(cssparams + one.main,true,(csserror,cssdata)=>{
					if(!csserror) one.main= cssdata;
					newresources.push(one);
					cb();
				});
			}else{
				newresources.push(one);
				cb();
			}
		},function(err){
			info.resources = newresources;
			callback();
		});
	}
}

function _getData(info,params,callback){
	const baseUrl = config.context?`/${config.context}/`:'/';
	let serviceData = {status:0,data:[]};
	let actionData = {status:0,data:[]};
	let data = {app:info};
	data.baseUrl = baseUrl;
	data.appConst = helper.json2string(appConst);
	data.CDNLibPath = config.CDNLibPath || "";
	data.CDNImagePath = config.CDNImagePath || "";
	data.CDNMediaPath = config.CDNMediaPath || "";
	
	let exs = [];
	if(info.before_service){
		exs.push({type:'service',params:params,name:info.before_service});
	}
	
	if(info.before_action){
		exs.push({type:'action',params:params,name:info.before_action});
	}
	
	helper.async(exs,function(one,cb){
		let exeobj,exefun,data;
		if(one.type === 'service'){
			exeobj = new service(one.name);
			exefun = 'invoke';
			data = serviceData;
		}else if(one.type === 'action'){
			exeobj = new action(one.name);
			exefun = 'excute';
			data = actionData;
		}

		exeobj[exefun](one.params).then(result=>{
			data.data = result;
			cb();
		}).catch(err=>{
			data.status = 1;
			data.msg = err;
			cb();
		});

	},function(err){
		data.serviceData = helper.json2string(serviceData);
		data.actionData = helper.json2string(actionData);
		callback(data);
	});
}


class application{
  constructor(app_name){
    this.app_name = app_name;
  }
  
  render(params,query){
    let app_name = this.app_name;
		
    return new Promise((resolve, reject)=>{
      application.find(app_name).then(info=>{
				if(info.disabled === CONST.DISABLED_TYPES.DISABLED){
					reject(error.GONE);
				}else{
					
					_getData(info,params,function(data){
						data.query = helper.json2string(query);
						
						template.render('index',data).then(result=>{
							resolve(result);
						}).catch(err=>{
							reject(err);
						});
					});
				}
      }).catch(err=>{
        reject(err);
      });
    });
  }
  
  static find(app_name){
    return new Promise((resolve, reject)=>{
      if(!app_name) return reject(error.NOT_FOUND_APPLICATION_NAME);
      
			if(CONST.APPLICATIONS[app_name]){
        return resolve(CONST.APPLICATIONS[app_name]);
      }
			
      let info = cache.getApplication(app_name);
			
      if(info){
        resolve(info);
      }else{
        datasource.systemQuery(CONST.SQLS.application_browse,[app_name,app_name]).then(result=>{
          info = result[0];
          if(info){
						datasource.systemQuery(CONST.SQLS.resource_browsebyappid,[info.id]).then(result=>{
              info.resources = result;
							let data2 = {
								appname: info.name
								,CDNLibPath: config.CDNLibPath || ""
								,CDNImagePath: config.CDNImagePath || ""
								,CDNMediaPath: config.CDNMediaPath || ""
							};
							
							data2.imgPath = data2.CDNImagePath + data2.appname + '/';
							data2.imgCommonPath = data2.CDNImagePath + 'common/';
							data2.libPath = data2.CDNLibPath + data2.appname + '/';
							data2.mediaPath = data2.CDNMediaPath + data2.appname + '/';
							data2.mediaCommonPath = data2.CDNMediaPath + 'common/';
							
							dealCode(info,data2,function(){
								cache.setApplication(app_name,info);
								resolve(info);
							});
            }).catch(err=>{
              reject(err);
            });
          }else{
            reject(error.NOT_FOUND_APPLICATION_NAME);
          }
        }).catch(err=>{
          reject(err);
        });
      }
    });
  }
}
module.exports = application;
